#include "TestCases.h"
#include "Coordinate.h"
#include "Problem.h"
#include "problem1.h"

void TestCases::testCoordinate(){
    std::cout<<" \n \n\nTesting Coordinate \n"<<std::endl;

    Coordinate *cor1=new Coordinate;
    std::cout<<"\n\n///////Coordinate case 1///////expected output: cor1; 1 lower : -3 upper: 3; 1;/////////////"<<std::endl;
    cor1->addPointer(cor1,"cor1");
    cor1->printPointerNames();
    cor1->printCoordinate();
    std::cout<<cor1->getNumPointers()<<std::endl;


    Coordinate *cor2=new Coordinate(-1,7);
    std::cout<<"\n\n///////Coordinate case 2///////expected output: cor2; 0 lower : -1 upper: 7; 1;/////////////"<<std::endl;
    (*cor2).addPointer(cor2, "cor2");
    (*cor2).printPointerNames();
    cor2->setContinious(false);
    cor2->printCoordinate();
    std::cout<<cor1->getNumPointers()<<std::endl;
    delete cor2;
    cor2=0;


    Coordinate cor4;
    std::cout<<"\n\n///////Coordinate case 3///////expected output: 1 lower : -4 upper: 3; 0;/////////////////"<<std::endl;
    cor4.setLowerBound(-4);
    cor4.printCoordinate();
    std::cout<<cor4.getNumPointers()<<std::endl;

    //error couse coping constructor for this class is forbiden
    //    Coordinate cor5=cor4;

    Coordinate *cor3=cor1;
    std::cout<<"\n\n///////Coordinate case 4///////expected output: cor1 cor3; 1 lower : -3 upper: 3; 2; yes they store the same";
    std::cout<<" address; no they dont store the same address; cor1 and cor3 both point to null//////////////"<<std::endl;
    cor3->addPointer(cor3, "cor3");
    cor1->printPointerNames();
    (*cor3).printCoordinate();
    std::cout<<(*cor1).getNumPointers()<<std::endl;
    if(cor1==cor3)
        std::cout<<"yes they store the same address"<<std::endl;

    //########################!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!#######################################################
    //delete all pointers(dynamiclly alocated memory using new
    //so find in the code all new keywords and when they can go do delete
    //so don't need to do anythink with cor3 just make sure it is no longer used after deleting cor1
    delete cor1;
    //cor1 and cor3 must point to zero now
    //each pointer pointed to this object assign to 0
    //get pointers of this object before it is deleted and call assignZero method
    cor1=0;
    //vallllllllgrind complains
    // cout<<cor3->getNumPointers()<<endl;
    //segmentation fault
    //cout<<cor1->getNumPointers()<<endl;
    //it is not printed
    if(cor1!=cor3)
        std::cout<<"no they dont store the same address"<<std::endl;
    cor3=0;
    //it is printed this time couse both cor1 and cor3 are null pointers
    if(cor1==cor3)
        std::cout<<"cor1 and cor3 both point to null"<<std::endl;
}


void TestCases::testProblem(){
    std::cout<<" \n\n\n Testing Problem \n"<<std::endl;

    double a1[]= {6.987,9.87,9,4.0,0};
    std::vector<double> av1(a1, &a1[sizeof(a1) / sizeof(a1[0])]);

    Problem * p=new problem1(5);
    std::cout<<"\n\n///////Problem case 1///////expected output:dimention: 5; is minimum: 1; is known global optimum: 0; bestKnownMin : 0; ";
    std::cout<<"243.235; 243.235; -3; -9/////////////"<<std::endl;
    (*p).printProblem();
    std::cout<<(*p).computeValue(a1)<<std::endl;
    std::cout<<(*p).computeValue(av1)<<std::endl;
    //coordinate set by default lower bound
    std::cout<<(*p).getCoordinates()[2].getLowerBound()<<std::endl;
    (*p).getCoordinates()[2].setLowerBound(-9);
    //after setting to different value
    std::cout<<(*p).getCoordinates()[2].getLowerBound()<<std::endl;
    //delete the same as calling destructor, since destructor is called automaticcly when object is going out of scope and
    //object goes out of scope when it is deleted
    // p.problem1::~problem1()
    delete p;
    p=0;



    Problem * pv=new problem1(av1.size());
    std::cout<<"\n\n///////Problem case 2///////expected output:dimention: 5; is minimum: 1; is known global optimum: 0; bestKnownMin : 0; ";
    std::cout<<"243.235;/////////////"<<std::endl;
    (*pv).printProblem();
    std::cout<<(*pv).computeValue(av1)<<std::endl;
    delete pv;
    pv=0;



    double a2[]= {0, 2.8, 5.7654, 4};
    problem1 * p2=new problem1(4);
    std::cout<<"\n\n///////Problem case 3///////expected output:dimention: 4; is minimum: 1; is known global optimum: 1;";
    std::cout<<" bestKnownMin : 0;  57.0798/////////////"<<std::endl;
    p2->printProblem();
    std::cout<<p2->computeValue(a2)<<std::endl;
    delete p2;
    p2=0;



    double a3[]= {1,3,6,3,2,2,0};
    double a4[]= {0,0,0,0};
    std::vector<double> av3(a3, &a3[sizeof(a3) / sizeof(a3[0])]);
    std::vector<double> av4(a4, &a4[sizeof(a4) / sizeof(a4[0])]);
    //can not declare variable to be of abstract type Problem, couse it is notdynamic memory allocation
    problem1 p3(av3.size());
    std::cout<<"\n\n///////Problem case 4///////expected output:dimention: 7; is minimum: 1; is known global optimum: 0;";
    std::cout<<" bestKnownMin : 0; 63; 0; /////////////"<<std::endl;
    p3.printProblem();
    std::cout<<p3.computeValue(av3)<<std::endl;
    std::cout<<p3.computeValue(av4)<<std::endl;





}
void TestCases::testMethod(){
std::cout<<" \n\n\n Testing Method \n"<<std::endl;
std::cout<<" nothing to be done here "<<std::endl;
}
void TestCases::test(){
    testCoordinate();
    testProblem();
    testMethod();
}

TestCases::TestCases()
{
    //ctor
}

TestCases::~TestCases()
{
    //dtor
}
template <class T>
void TestCases::printNoLine(const T & a)
{
  std::cout<<" "<<a<<"   ";
}
template <class T>
void TestCases::print(const T & a) {
std::cout<<a<<std::endl;
}
